package com.rickpan.service.impl;

import com.rickpan.entity.Project;
import com.rickpan.entity.ProjectTask;
import com.rickpan.entity.TeamMember;
import com.rickpan.exception.BusinessException;
import com.rickpan.repository.ProjectRepository;
import com.rickpan.repository.ProjectTaskRepository;
import com.rickpan.repository.TeamMemberRepository;
import com.rickpan.service.ProjectService;
import com.rickpan.service.ProjectTaskService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.util.List;
import java.util.Optional;

/**
 * 项目任务服务实现类
 * 
 * @author RickPan Team
 * @since 2024-01-15
 */
@Service
@Transactional
public class ProjectTaskServiceImpl implements ProjectTaskService {

    private static final Logger logger = LoggerFactory.getLogger(ProjectTaskServiceImpl.class);

    @Autowired
    private ProjectTaskRepository taskRepository;

    @Autowired
    private ProjectRepository projectRepository;

    @Autowired
    private TeamMemberRepository teamMemberRepository;

    @Autowired
    @Lazy
    private ProjectService projectService;

    @Override
    public ProjectTask createTask(ProjectTask task) {
        logger.info("创建任务: {}, 项目ID: {}", task.getTitle(), task.getProjectId());

        // 检查项目是否存在
        Project project = projectRepository.findById(task.getProjectId())
                .orElseThrow(() -> new BusinessException("项目不存在: " + task.getProjectId()));

        // 设置初始状态
        if (task.getStatus() == null) {
            task.setStatus(ProjectTask.Status.TODO);
        }

        // 保存任务
        ProjectTask savedTask = taskRepository.save(task);

        // 更新项目进度
        projectService.updateProjectProgress(task.getProjectId());

        return savedTask;
    }

    @Override
    public ProjectTask updateTask(ProjectTask task) {
        logger.info("更新任务: {}, ID: {}", task.getTitle(), task.getId());

        // 检查任务是否存在
        ProjectTask existingTask = taskRepository.findById(task.getId())
                .orElseThrow(() -> new BusinessException("任务不存在: " + task.getId()));

        // 保存任务
        ProjectTask updatedTask = taskRepository.save(task);

        // 更新项目进度
        projectService.updateProjectProgress(task.getProjectId());

        return updatedTask;
    }

    @Override
    public void deleteTask(Long taskId) {
        logger.info("删除任务: {}", taskId);

        // 检查任务是否存在
        ProjectTask task = taskRepository.findById(taskId)
                .orElseThrow(() -> new BusinessException("任务不存在: " + taskId));

        // 删除任务
        taskRepository.deleteById(taskId);

        // 更新项目进度
        projectService.updateProjectProgress(task.getProjectId());
    }

    @Override
    @Transactional(readOnly = true)
    public Optional<ProjectTask> findById(Long taskId) {
        return taskRepository.findById(taskId);
    }

    @Override
    @Transactional(readOnly = true)
    public List<ProjectTask> findTasksByProject(Long projectId) {
        return taskRepository.findByProjectIdOrderByCreatedAtDesc(projectId);
    }

    @Override
    @Transactional(readOnly = true)
    public Page<ProjectTask> findTasksByProject(Long projectId, Pageable pageable) {
        return taskRepository.findByProjectIdOrderByCreatedAtDesc(projectId, pageable);
    }

    @Override
    @Transactional(readOnly = true)
    public List<ProjectTask> findTasksByProjectAndStatus(Long projectId, ProjectTask.Status status) {
        return taskRepository.findByProjectIdAndStatusOrderByCreatedAtDesc(projectId, status);
    }

    @Override
    @Transactional(readOnly = true)
    public Page<ProjectTask> findTasksByProjectAndStatus(Long projectId, ProjectTask.Status status, Pageable pageable) {
        return taskRepository.findByProjectIdAndStatusOrderByCreatedAtDesc(projectId, status, pageable);
    }

    @Override
    @Transactional(readOnly = true)
    public List<ProjectTask> findTasksByAssignee(Long assigneeId) {
        return taskRepository.findByAssigneeIdOrderByDueDateAscCreatedAtDesc(assigneeId);
    }

    @Override
    @Transactional(readOnly = true)
    public List<ProjectTask> findTasksByAssigneeAndStatus(Long assigneeId, ProjectTask.Status status) {
        return taskRepository.findByAssigneeIdAndStatusOrderByDueDateAscCreatedAtDesc(assigneeId, status);
    }

    @Override
    @Transactional(readOnly = true)
    public List<ProjectTask> findTasksByCreator(Long creatorId) {
        return taskRepository.findByCreatorIdOrderByCreatedAtDesc(creatorId);
    }

    @Override
    @Transactional(readOnly = true)
    public List<ProjectTask> searchTasks(Long projectId, String keyword) {
        return taskRepository.searchTasksByProject(projectId, keyword);
    }

    @Override
    @Transactional(readOnly = true)
    public Page<ProjectTask> searchTasks(Long projectId, String keyword, Pageable pageable) {
        return taskRepository.searchTasksByProject(projectId, keyword, pageable);
    }

    @Override
    @Transactional(readOnly = true)
    public List<ProjectTask> findTasksDueSoon(int days) {
        LocalDateTime now = LocalDateTime.now();
        LocalDateTime future = now.plusDays(days);
        return taskRepository.findTasksDueSoon(now, future);
    }

    @Override
    @Transactional(readOnly = true)
    public List<ProjectTask> findOverdueTasks() {
        return taskRepository.findOverdueTasks(LocalDateTime.now());
    }

    @Override
    @Transactional(readOnly = true)
    public List<ProjectTask> findOverdueTasksByProject(Long projectId) {
        return taskRepository.findOverdueTasksByProject(projectId, LocalDateTime.now());
    }

    @Override
    @Transactional(readOnly = true)
    public List<ProjectTask> findOverdueTasksByAssignee(Long assigneeId) {
        return taskRepository.findOverdueTasksByAssignee(assigneeId, LocalDateTime.now());
    }

    @Override
    public void updateTaskStatus(Long taskId, ProjectTask.Status status) {
        logger.info("更新任务状态: {}, 状态: {}", taskId, status);

        // 检查任务是否存在
        ProjectTask task = taskRepository.findById(taskId)
                .orElseThrow(() -> new BusinessException("任务不存在: " + taskId));

        // 更新状态
        task.setStatus(status);

        // 如果状态为已完成，设置完成时间
        if (status == ProjectTask.Status.COMPLETED && task.getCompletedAt() == null) {
            task.setCompletedAt(LocalDateTime.now());
        }

        // 保存任务
        taskRepository.save(task);

        // 更新项目进度
        projectService.updateProjectProgress(task.getProjectId());
    }

    @Override
    public void assignTask(Long taskId, Long assigneeId) {
        logger.info("分配任务: {}, 分配给: {}", taskId, assigneeId);

        // 检查任务是否存在
        ProjectTask task = taskRepository.findById(taskId)
                .orElseThrow(() -> new BusinessException("任务不存在: " + taskId));

        // 更新分配者
        task.setAssigneeId(assigneeId);

        // 保存任务
        taskRepository.save(task);
    }

    @Override
    @Transactional(readOnly = true)
    public TaskStatistics getTaskStatistics(Long projectId) {
        // 获取项目任务总数
        long totalTasks = taskRepository.countByProjectId(projectId);
        
        // 获取待办任务数
        long todoTasks = taskRepository.countByProjectIdAndStatus(projectId, ProjectTask.Status.TODO);
        
        // 获取进行中任务数
        long inProgressTasks = taskRepository.countByProjectIdAndStatus(projectId, ProjectTask.Status.IN_PROGRESS);
        
        // 获取已完成任务数
        long completedTasks = taskRepository.countByProjectIdAndStatus(projectId, ProjectTask.Status.COMPLETED);
        
        // 获取逾期任务数
        long overdueTasks = findOverdueTasksByProject(projectId).size();
        
        return new TaskStatistics(totalTasks, todoTasks, inProgressTasks, completedTasks, overdueTasks);
    }

    @Override
    @Transactional(readOnly = true)
    public TaskStatistics getUserTaskStatistics(Long userId) {
        // 获取用户任务总数
        long totalTasks = taskRepository.countByAssigneeId(userId);
        
        // 获取待办任务数
        long todoTasks = taskRepository.countByAssigneeIdAndStatus(userId, ProjectTask.Status.TODO);
        
        // 获取进行中任务数
        long inProgressTasks = taskRepository.countByAssigneeIdAndStatus(userId, ProjectTask.Status.IN_PROGRESS);
        
        // 获取已完成任务数
        long completedTasks = taskRepository.countByAssigneeIdAndStatus(userId, ProjectTask.Status.COMPLETED);
        
        // 获取逾期任务数
        long overdueTasks = findOverdueTasksByAssignee(userId).size();
        
        return new TaskStatistics(totalTasks, todoTasks, inProgressTasks, completedTasks, overdueTasks);
    }

    @Override
    @Transactional(readOnly = true)
    public boolean hasTaskManagePermission(Long taskId, Long userId) {
        // 检查任务是否存在
        ProjectTask task = taskRepository.findById(taskId)
                .orElseThrow(() -> new BusinessException("任务不存在: " + taskId));
        
        // 检查用户是否是任务创建者
        if (task.getCreatorId().equals(userId)) {
            return true;
        }
        
        // 检查用户是否是任务分配者
        if (task.getAssigneeId() != null && task.getAssigneeId().equals(userId)) {
            return true;
        }
        
        // 检查用户是否有项目管理权限
        return projectService.hasProjectManagePermission(task.getProjectId(), userId);
    }

    @Override
    @Transactional(readOnly = true)
    public boolean hasTaskViewPermission(Long taskId, Long userId) {
        // 检查任务是否存在
        ProjectTask task = taskRepository.findById(taskId)
                .orElseThrow(() -> new BusinessException("任务不存在: " + taskId));
        
        // 检查用户是否有项目查看权限
        return projectService.hasProjectViewPermission(task.getProjectId(), userId);
    }
}
